<?php

/**
 * 
 * Autor				: 	Juan Jose Muñiz Juarez
 * Fecha de Creacion	: 	01/05/2012,  16:50:28
 * Version 				: 	1.0
 * Descripcion 			:
 */

if ( !defined( "RUTA_FISICA_SISTEMA" ) )
   {
      require_once '../../../../config/Constantes.php';
   }

$ruta_sistema = RUTA_FISICA_SISTEMA . "/sistema/";

require_once $ruta_sistema . "general/clases/comun/base_datos/ORMAbstractClass.php";
require_once $ruta_sistema . "general/clases/comun/GeneralORM.php";
require_once $ruta_sistema . "general/clases/comun/base_datos/DataBase.php";
require_once $ruta_sistema . "general/clases/comun/logger/Log.php";

class ORMMySQL extends ORMAbstractClass
   {
      private $_objeto;
      private $_tabla;
      private $_clase;
      private $_log;
      private $_campos;
      private $_campo_id;
      private $_autoincrement;
      
      /**
     * @param field_type $_autoincrement
     */
    public function setAutoincrement ( $_autoincrement )
         {
            $this->_autoincrement = $_autoincrement;
        }
   
	/**
     * @param Ambigous <multitype:multitype:Ambigous, NULL, Ambigous, string, unknown_type, unknown> $_campo_id
     */
    public function setCampo_id ( $_campo_id )
         {
            $this->_campo_id = $_campo_id;
        }
   
	public function __construct( $objeto )
        {
           if ( !$this -> _objeto )
             {
                
             }
             
           $this -> _objeto = $objeto;  
        }

        /**
         * 
         * Nombre         	: 	getLogger
         * Descripcion   	:	
         * Version 			:  	1.0
         * Autor:			:	Juan Jose Muñiz Juarez
         * Fecha y Hora		:	02/05/2012, 22:53:55
         */
      private function getLogger( )
        {
           if ( $this -> _log )
             {
                return $this -> _log;
             }
           else
             {
                $this -> _log = new Logger( $this -> getNameClass() ) ;
             }  
        }  
      /**
       *
       * Nombre        	: 	getNameClass
       * Descripcion   	:
       * Version 		:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora	:	29/04/2012, 22:17:11
       * @param unknown_type $this -> _objeto
       * @return string
       */
      private function getNameClass(  )
         {
            if ( !$this -> _clase )
              {
                /* $this -> getLogger();
                 
                 ;
                 $this -> _log -> info( "Obteniendo el nombre de la clase que deriva el objeto " . $this -> _clase );*/
                 $this -> _clase = get_class( $this -> _objeto );                
                 return $this -> _clase;
              }
            else 
              {
                 return $this -> _clase;
              }  
         }

      /**
       * 
       * Nombre         	: 	getNameTable
       * Descripcion   	:	
       * Version 		:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora	:	01/05/2012, 17:59:50
       * @param unknown_type $this -> _objeto
       */
      private function getNameTable(  )
         {
            if ( !$this -> _tabla )
              {
                 $this -> _tabla = GeneralORM :: getTabla( $this -> _objeto );
                 
                 $this -> getLogger();
                 $this -> _log -> info( "Obteniendo el nombre de la tabla[ " . $this -> _tabla . " ] del objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
                 
                 return $this -> _tabla;
              }
            else 
              {
                 return $this -> _tabla;
              }  
         }

      /**
       *
       * Nombre         	: 	obtenerVariables
       * Descripcion   	:
       * Version 			:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora		:	29/04/2012, 22:14:24
       * @param unknown_type $obj
       * @return multitype:NULL |multitype:
       */
      private function getCampos(  )
         {
            if ( !$this -> _campos )
              {
                if ( $this -> _objeto )
                  {
                     $this -> getLogger();
                     $this -> _log -> info( "Cargando la informacion de los campos del objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
                     
                     $this -> _campos = GeneralORM :: getCampos( $this -> _objeto );
                    
                     return $this -> _campos;
                  }
              }
            else
              {
                 return $this -> _campos;
              }  
              
            return array();  
         }
         
         /**
          * 
          * Nombre         	: 	getCampoId
          * Descripcion   	:	
          * Version 		:  	1.0
          * Autor:			:	Juan Jose Muñiz Juarez
          * Fecha y Hora	:	01/05/2012, 22:09:54
          * @param unknown_type $this -> _objeto
          * @return Ambigous <Ambigous, multitype:, multitype:multitype:Ambigous Ambigous <Ambigous, string, unknown_type, unknown>  >|NULL
          */
       private function getCampoId(  )
         { 
            $this -> getLogger();
            $this -> _log -> info( "Intentando obtener el campo Id del objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
                    
            if ( !$this -> _campo_id )
              {
                if ( $this -> _objeto )
                  {       
                    $this -> _campo_id = GeneralORM :: getCampoId( $this -> _objeto );
                    
                    if ( $this -> _campo_id )
                      { 
                        $this -> _log -> info( "El campo Id del objeto [ " . $this -> getNameClass() . " ] es [ " .$this -> _campo_id . " ]" , __METHOD__ , __LINE__ );
                      }  

                    return $this -> _campo_id;  
                  }
              }
            else
              {
                 $this -> _log -> info( "El campo Id del objeto [ " . $this -> getNameClass() . " ] es [ " .$this -> _campo_id . " ]" , __METHOD__ , __LINE__ );
                 return $this -> _campo_id;
              }  

            return null;
         }  
      /**
       * Metodo sobrecargado
       * Nombre        	: 	save
       * Descripcion   	:	
       * Version 		:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora	:	01/05/2012, 16:51:18
       * @param unknown_type $this -> _objeto
       */
      public function save( $campos_ignorar = null )
         {
            $this -> getLogger();
            $this -> _log -> info( "Se va a intentar guardar la informacion del objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
            
            self :: agregarInformacionTabla( $this -> _objeto, $campos_ignorar );
         }

      /**
       * 
       * Nombre         	: 	agregarInformacionTabla
       * Descripcion   	:	
       * Version 		:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora	:	01/05/2012, 21:10:48
       * @throws Exception
       * @return Ambigous <NULL, resource>
       */
      private function agregarInformacionTabla( $campos_ignorar = null, $actualizar = false )
         {
            if ( !$this -> _objeto )
               {
                  throw new Exception( "");
               }

            // Obtenemos el nombre de la tabla
            $tabla = $this -> getNameTable( );

            if ( !$actualizar )
               {
                  // Generamos la consulta correspondiente al insert en MySQL
                  $query = "Insert Into $tabla ";
               }
            else
               {
                  $query = "Update $tabla ";
               }
            // Obtenemos los campos de la tabla

            $campos = $this -> getCampos( );
            $campos_id = array ( );
            $valores = array ( );
            $campo_id = "";

            $info_campos = "";

            if ( $campos )
               {
                  if ( is_array( $campos ) && count( $campos ) > 0 )
                     {
                        $contador = 0;

                        foreach ( $campos as $campo )
                           {
                              //var_dump( $campo );
                              if ( $campo )
                                 {
                                    if ( is_array( $campo ) && count( $campo ) )
                                       {
                                          // Verificamos si el campo es el identificador de la tabla para omitirlo
                                          $id = false;

                                          if ( !$this -> _campo_id )
                                            {
                                                if ( isset( $campo [ "id" ] ) )
                                                   {
                                                      if ( $campo [ "id" ] == "1" )
                                                         {
                                                             if ( !$actualizar )
                                                              {
                                                                  //var_dump( $info_campos );
                                                                  // Ahora verificamos si es autoincremental para omitirlo
                                                                  if ( isset( $campo [ "autoincrement" ] ) )
                                                                     {
                                                                        //var_dump( $campo[ "autoincrement" ] );
            
                                                                        if ( $campo [ "autoincrement" ] == "1" )
                                                                           {
                                                                              $campos_id [ $campo [ "columna" ] ] = "0";
                                                                              continue;
                                                                           }
                                                                     }
      
                                                                  $id = true;
                                                                  $this -> _autoincrement = false;
                                                              }
                                                              
                                                              $campo_id = $campo[ "columna" ];
                                                         }
                                                   }
                                            }                                            

                                          if ( $id )
                                             {
                                                if ( !$this -> _autoincrement )
                                                  {
                                                     $valores [ $campo [ "columna" ] ] = $this -> generarID( $tabla, $campo [ "columna" ] );
                                                  }
                                             }
                                          else
                                             {
                                                if ( $campos_ignorar )
                                                   {
                                                      if ( stripos( $campos_ignorar, $campo [ "columna" ] ) !== false )
                                                         {
                                                            continue;
                                                         }
                                                   }

                                                $valores [ $campo [ "columna" ] ] = $this -> getValorCampo( $this -> _objeto, $campo [ "columna" ] );
                                             }

                                          $info_campos .= ( $contador > 0 ? "," : "" ) . $campo [ "columna" ];

                                          $contador++;
                                       }
                                 }
                           }
                     }
               }

            if ( !$actualizar )
              {
                 // Añadimos lo campos al query
                 $query .= "( $info_campos )";
              }
              
            // Añadimos los valores de los campos
            $query .= $this -> generarCadenaValues( $valores, $campo_id, $actualizar );

            //var_dump( $query );
            // Ejecutamos la consulta
            if ( $actualizar )
              {
                 $this -> getLogger();
                 $this -> _log -> info( "Se va a proceder a actualizar la informacion del objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
                 
                 $actualizado = DataBase::update( $query, $this -> getNameClass(  ) );
                 
                 if ( $actualizado )
                   {
                      $this -> _log -> info( "La informacion del objeto [" . $this -> getNameClass() . "] se ha actualizado", __METHOD__ , __LINE__ );
                   }
                 else
                   {
                      $this -> _log -> info( "Ocurrio un error al intentar actualizar La informacion del objeto [" . $this -> getNameClass() . "]", __METHOD__ , __LINE__ );
                   }  
                   
                 return $actualizado;  
              }
            else  
              {
                 $this -> getLogger();
                 $this -> _log -> info( "Se va a proceder a guardar la informacion del objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
                 
                 $almacenado = DataBase :: insert( $query, $this -> getNameClass(  ) );
                 
                 if ( $almacenado )
                   {
                      $this -> _log -> info( "La informacion del objeto [" . $this -> getNameClass() . "] se ha almacenado", __METHOD__ , __LINE__ );
                   }
                 else
                   {
                      $this -> _log -> info( "Ocurrio un error al intentar guardar la inforamcion del objeto [" . $this -> getNameClass() . "]", __METHOD__ , __LINE__ );
                   }  
                   
                 return $almacenado;  
              }
         }

      /**
       * 
       * Nombre         	: 	generarID
       * Descripcion   	:	
       * Version 			:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora		:	01/05/2012, 19:00:46
       * @param unknown_type $tabla
       * @param unknown_type $campo
       */
      private function generarID( $tabla, $campo )
         {
            //var_dump( $tabla, $campo );
            if ( !$tabla && !$campo )
               {

               }

            $this -> getLogger();
            $this -> _log -> info( "Se va proceder a obtener el valor del id para el objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
            
            $resultado = $this -> query( "Select count( $campo ) + 1 as id from $tabla limit 1 " );

            if ( $resultado )
               {
                  $this -> _log -> info( "Se ha obtenido el valor del id[ " . $resultado [ "id" ]. " ] para el objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
                  return $resultado [ "id" ];
               }

            return 1;
         }

      /**
       * 
       * Nombre         	: 	getValorCampo
       * Descripcion   	:	
       * Version 			:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora		:	01/05/2012, 19:11:33
       * @param unknown_type $this -> _objeto
       * @param unknown_type $campo
       */
      private function getValorCampo( $campo )
         {
            $this -> getLogger();
            $metodo = "get" . ucfirst( $campo );
            $this -> _log -> info( "Invocando el metodo $metodo del objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
            return GeneralORM :: getValorObjeto( $this -> _objeto, $metodo );
         }
         
         /**
          * 
          * Nombre         	: 	setValorCampo
          * Descripcion   	:	
          * Version 			:  	1.0
          * Autor:			:	Juan Jose Muñiz Juarez
          * Fecha y Hora		:	01/05/2012, 22:30:33
          * @param unknown_type $this -> _objeto
          * @param unknown_type $campo
          * @param unknown_type $valor
          */
      private function setValorCampo( $campo, $valor, $objeto = null )
         {
            $this -> getLogger();
            
            $metodo = "set" . ucfirst( $campo );
            $this -> _log -> info( "Invocando el metodo $metodo con el valor $valor del objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
            
            //var_dump( $campo , $objeto );
            
            return GeneralORM :: setValorObjeto( $objeto ? $objeto : $this -> _objeto, $metodo, $valor );
         }   

      /**
       * 
       * Nombre         	: 	generarCadenaValues
       * Descripcion   	:	
       * Version 		:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora	:	01/05/2012, 19:15:39
       * @param unknown_type $valores
       * @return string
       */
      private function generarCadenaValues( $valores, $id = "", $update = false )
         {
            if ( !$valores )
               {

               }
 
            $cadena = $update ? "SET " : " Values ( ";
            $where = " Where ";

            $contador = 0;

            foreach ( $valores as $key => $valor )
               {
                  if ( $update )
                     {
                        if ( $id != $key )
                          {
                             $cadena .= ( $contador > 0 ? "," : "" ) . " $key = '$valor'";
                          }
                        else
                         {
                            $where .= "$key = '$valor'"; 
                            $contador--;
                         }  
                     }
                  else
                     {
                        $cadena .= ( $contador > 0 ? "," : "" ) . "'$valor'";
                     }

                  $contador++;
               }

            $cadena .= $update ? $where : " )";

            return $cadena;
         }

      /**
       * Metodo sobrecargado
       * Nombre         	: 	update
       * Descripcion   	:	
       * Version 			:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora		:	01/05/2012, 16:51:18
       * @param unknown_type $this -> _objeto
       */
      public function update( $campos_ignorar = null )
         {
            $this -> getLogger();
            $this -> _log -> info( "Se va a proceder a actualizar la informacion del objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
            
            self :: agregarInformacionTabla( $this -> _objeto, $campos_ignorar, true );
         }

      /**
       * Metodo sobrecargado
       * Nombre         	: 	delete
       * Descripcion   	:	
       * Version 			:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora		:	01/05/2012, 16:51:18
       * @param unknown_type $this -> _objeto
       */
      public function delete( $filtro = null )
         {
            if ( !$this -> _objeto )
               {
                  throw new Exception( "");
               }

            $this -> getLogger();
            $this -> _log -> info( "Eliminando la informacin del objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
               
            // Obtenemos el nombre de la tabla
            $tabla = $this -> getNameTable( $this -> _objeto );

            // Generamos la consulta correspondiente al insert en MySQL
            $query = "Delete From $tabla";
            
            if ( !$filtro )
              {
               // Obtenemos los campos de la tabla
               $id = $this -> getCampoId( $this -> _objeto );
               
               if ( $id )
                 {
                    $query .= " Where $id = '" . $this -> getValorCampo( $this -> _objeto, $id ) . "'";
                 }
              }
            else
              {
                 $query .= " " . $filtro;
              }  
              
            return DataBase::delete( $query, $this -> getNameClass( ) );  
         }

      /**
       * Metodo sobrecargado
       * Nombre         	: 	find
       * Descripcion   	:	
       * Version 			:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora		:	01/05/2012, 16:51:18
       * @param unknown_type $id
       */
      public function find( $id = null, $filtro = null )
         {
            if ( !$this -> _objeto )
               {
                  throw new Exception( "" );
               }
               
            $this -> getLogger();
            $this -> _log -> info( "Buscando la informacion del objeto con el id[ $id ] y/o filtro[ $filtro] " . $this -> getNameClass(), __METHOD__ , __LINE__ );

            // Obtenemos el nombre de la tabla
            $tabla = $this -> getNameTable( );

            // Generamos la consulta correspondiente al insert en MySQL
            $query = "Select * From $tabla";
            
            if ( !$filtro )
              {
                 if ( $id )
                   {
                      // Obtenemos los campos de la tabla
                     $campo_id = $this -> getCampoId( );
                     
                     if ( $campo_id )
                       {
                          $query .= " Where $campo_id = '" . ( $id ? $id : $this -> getValorCampo( $campo_id ) ). "'";
                       }
                   }
              }
            else
              {
                 $query .= " " . $filtro;
              }  
              
            $resultados = DataBase::query( $query );

            if ( $resultados )
              {
                 $total = mysql_num_rows( $resultados );
                 $objetos = array();
                 $objeto = $this -> _objeto;
                 
                 //var_dump( $objeto );
                 
                 if ( $total > 1 )
                   {
                     // echo "Entro";
                     $objetos = array();
                      
                     while ( $datos = mysql_fetch_assoc( $resultados ) )
                       {
                         //$tmp_objeto = $objeto;
                         $objeto = clone $this -> _objeto;
                        // var_dump( "Objeto Inicial" , $objeto );
                         $this -> cargarDatosObjeto( $datos , $objeto );
                         $objetos[ ] = $objeto;
                         
                         
                        // var_dump( "Objeto creado" , $objeto );
                       }
                     
                    // var_dump( $objetos );  
                       
                     //$this -> _objeto = $objeto;
                     
                       return $objetos;
                   }
                 else
                  {
                     //echo "Entro";
                     $datos = mysql_fetch_assoc( $resultados );
                     $this -> cargarDatosObjeto( $datos, $this -> _objeto );
                     
                     return $this -> _objeto;
                  }  
                  
                 return $objetos;
              }
              
             return null;  
         }

         /**
          * 
          * Nombre         	: 	cargarDatosObjeto
          * Descripcion   	:	
          * Version 			:  	1.0
          * Autor:			:	Juan Jose Muñiz Juarez
          * Fecha y Hora		:	01/05/2012, 22:32:03
          * @param unknown_type $resultados
          * @param unknown_type $this -> _objeto
          */
      private function cargarDatosObjeto( $resultados, $objeto = null )
        {
           if ( !$resultados && !$this -> _objeto )
             {
                
             }
             
           $campos = $this -> getCampos( );
           
           if ( $campos )
             {
                foreach ( $campos as $campo )
                  {
                     //var_dump( "Campo: ",  $campo );
                     if ( $campo )
                        {
                           if ( is_array( $campo ) && count( $campo ) )
                              {
                                  $this -> setValorCampo( $campo [ "columna" ], $resultados[ $campo [ "columna" ] ], $objeto ); 
                              }
                        }
                  }
             }
             
             
        }   

      /**
       * Metodo sobrecargado
       * Nombre         : 	query
       * Descripcion   	:	
       * Version 		:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora		:	01/05/2012, 16:51:18
       * @param unknown_type $query
       */
      public function query( $query )
         {
            if ( !$query )
               {

               }

            /* $query = "Select " . ( $campo ? $campo : "*" ). 
                      " From " . self::getNameTable( $this -> _objeto ) . 
                      " " . $query;  
             */
            //var_dump( $query );

            $this -> getLogger();
            $this -> _log -> info( "Ejecutando la siguiente query $query " . $this -> getNameClass(), __METHOD__ , __LINE__ );
            
            $resultado = mysql_query( $query, Conexion :: getConexion( get_class( ) ) );

            return $resultado;
         }
      /**
       * Metodo sobrecargado
       * Nombre         	: 	load
       * Descripcion   	:	
       * Version 			:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora		:	01/05/2012, 17:26:03
       * @param unknown_type $this -> _objeto
       */
      public function load( $id )
         {
            $this -> getLogger();
            $this -> _log -> info( "Cargando la informacion con id: $id del objeto" . $this -> getNameClass(), __METHOD__ , __LINE__ );
            return $this -> find( $id );
         }
      /**
       * Metodo sobrecargado
       * Nombre         	: 	findById
       * Descripcion   	:	
       * Version 			:  	1.0
       * Autor:			:	Juan Jose Muñiz Juarez
       * Fecha y Hora		:	01/05/2012, 17:33:22
       * @param unknown_type $id
       */
      public function findById( $id )
         {
            $this -> getLogger();
            $this -> _log -> info( "Buscando el id:$id para el objeto " . $this -> getNameClass(), __METHOD__ , __LINE__ );
            
            return $this -> find( $id );
         }
         
      public function findAll( $filtro = null )
        {
           $this -> getLogger();
           $this -> _log -> info( "Cargando todos los regisros y generando los objetos del tipo [" . $this -> getNameClass() . "] con el siguiente filtro[$filtro]", __METHOD__ , __LINE__ );
            
           return $this -> find( null, $filtro ); 
        }

   }